Skip to content

feat(tui): render assistant transcript with Markdown via OpenTUI markdown component - #39

Closed
knqiufan wants to merge 1 commit into
stepfun-ai:mainfrom
knqiufan:feat/tui-markdown-rendering
Closed

knqiufan wants to merge 1 commit into
stepfun-ai:mainfrom
knqiufan:feat/tui-markdown-rendering

Conversation

@knqiufan

@knqiufan knqiufan commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #35

The TUI transcript panel previously rendered all messages (including assistant responses) as plain text via <text> + <span>, losing all Markdown formatting — code blocks, tables, bold/italic, lists, and links were displayed as raw characters.

@opentui/react already ships a <markdown> JSX component backed by MarkdownRenderable (with marked parsing + tree-sitter syntax highlighting), but it was never used in the transcript.

Changes

  • Role-based rendering: Assistant messages now render through the <markdown> component with full Markdown support (code blocks, tables, bold/italic, lists, links). User/tool/system messages retain existing plain-text rendering unchanged.
  • Extract transcript data-building logic into src/tui/transcript-items.ts: TranscriptItem interface, buildTranscriptItems, buildWelcomeTranscriptItem, resolveTranscriptIdentity, resolveTranscriptBackground, wrapMultiline, sliceByDisplayWidth — all previously private to app.tsx, now independently importable and testable.
  • Add src/tui/transcript-syntax-style.ts: buildSyntaxStyleFromTheme() maps TUI theme colors to SyntaxStyle for code highlighting, so code blocks follow the active theme.
  • Extend TranscriptItem with content: string (raw Markdown text) and useMarkdown: boolean fields.
  • Update TranscriptEntry component: when useMarkdown is true, renders badge line + <markdown> block with table/code support; when false, keeps the original plain-text path.
  • Add 21 unit tests in src/tui/transcript-items.test.ts covering buildTranscriptItems (per-role behavior), resolveTranscriptIdentity, resolveTranscriptBackground, buildWelcomeTranscriptItem, wrapMultiline, and sliceByDisplayWidth.

Before / After

Markdown element Before After
Code blocks (```) Plain text Syntax-highlighted via tree-sitter
Tables Plain text Rendered with borders and column layout
Bold / Italic Raw ** / _ Rendered as <strong> / <em>
Links Raw URL text Rendered as clickable link
Lists / Headings No hierarchy Proper block-level rendering
Inline code No distinction Styled inline code
User/tool/system Plain text Plain text (unchanged)

Test plan

  • Run pnpm vitest run src/tui/transcript-items.test.ts — 21 new tests pass
  • Run lint, dep-guard, deadcode, tsc, prettier — all pass on this branch
  • Start TUI (step exec), send a prompt that returns Markdown with code blocks — verify syntax highlighting renders
  • Send a prompt that returns a Markdown table — verify table renders with borders
  • Send a prompt with bold/italic text — verify text modifiers render
  • Verify user input still renders as plain text (no Markdown parsing)
  • Verify tool output still renders with compact preview (truncation logic unchanged)
  • Switch themes (/theme sage, /theme default) — verify code highlighting colors update
  • Scroll through long Markdown content in transcript — verify scrollbox behavior

@ZouR-Ma

ZouR-Ma commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the contribution!

To get this ready to merge:

  • Reference an issue in the description with Closes #<number> (our link-check CI requires it; open one first if needed).
  • Make sure pnpm check passes locally (lint, type-check, dependency/dead-code guards, formatting, and tests — also enforced in CI).

Full conventions:
https://github.com/stepfun-ai/Step-Realtime-CLI/blob/main/CONTRIBUTING.md

@knqiufan

knqiufan commented Jun 21, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @ZouR-Ma for the review guidance!

Ready for review when you have a moment.

@ZouR-Ma

ZouR-Ma commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Status update: #32 has landed on main and touched app.tsx, and since you moved buildTranscriptItems into a new module, this PR now conflicts and needs a rebase first. We still want this feature — the list before it lands is the same as before, plus a new item 0:

  1. (Must) Rebase to resolve the conflict. #32 is on main now; when you rebase, carry its hidden-entry filter (.filter((entry) => !entry.hidden)) into buildTranscriptItems in transcript-items.ts and add a matching case to the new test file.
  2. (Must) Verify and handle Markdown behavior under streaming. Transient assistant entries (local-opentui-bridge.ts:185-189) grow incrementally during streaming and now feed into <markdown streaming={false}> — a full re-parse per delta, with unterminated code fences rendering broken mid-stream. Pick one: wire the streaming prop; render in-flight entries as plain text and switch on completion; or test the long-code-block streaming scenario and post the results.
  3. (Must) Execute the seven manual test-plan items, with at least one pass on the installed step binary rather than pnpm tui:dev. The unit tests cover data building, not rendering, and the tree-sitter/Markdown assets go through the tsdown bundle — the empty-chunk incident in #25 shows that pipeline has bitten before.
  4. (Must) Reopen issue #35. It was closed ahead of time; it should stay open and be auto-closed by this PR on merge — we can flip it back on our side.

CI is green across all three platforms, so that's not a concern. We want this feature — ping us once the rebase and verification are in.

@knqiufan
knqiufan force-pushed the feat/tui-markdown-rendering branch from ac379b4 to 77350ff Compare July 17, 2026 16:58
@github-actions github-actions Bot added the area/cli src/main.ts, src/cli.tsx, src/i18n.ts, src/version.ts, src/utils label Jul 17, 2026
…down component

The TUI transcript panel previously rendered all messages as plain
text, losing formatting such as code blocks, tables, bold/italic,
lists, and links in assistant responses.

This commit introduces role-based rendering: assistant messages now
use the built-in markdown component from @opentui/react with
tree-sitter syntax highlighting and theme-aware styling, while
user/tool/system messages retain their existing plain-text rendering.

Key changes:
- Extract transcript data-building logic into transcript-items.ts
  (buildTranscriptItems, wrapMultiline, sliceByDisplayWidth, etc.)
- Add transcript-syntax-style.ts with buildSyntaxStyleFromTheme()
  that maps TUI theme colors to SyntaxStyle for code highlighting
- Extend TranscriptItem with content/useMarkdown fields
- Update TranscriptEntry to branch on useMarkdown: true renders
  markdown with table/code support, false keeps plain-text path
- Add 21 unit tests covering all extracted functions

Closes #35
@knqiufan
knqiufan force-pushed the feat/tui-markdown-rendering branch from 77350ff to 6e3fc71 Compare July 17, 2026 17:00
@knqiufan

knqiufan commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed follow-up. I have rebased #39 onto current main (87c3445) and resolved the app.tsx conflict.

Changes made:

  • Preserved fix(tui): hide plugin-injected system reminders from transcript #32's hidden-entry filter in transcript-items.ts and added coverage for hidden entries.
  • Preserved the current collapsible tool and reasoning transcript behavior.
  • Wired Markdown streaming state from the local OpenTUI bridge: transient assistant entries use streaming mode while deltas arrive, then finalize after the assistant message (including the tool-call boundary). Added coverage for an incomplete fenced code block during streaming.

Validation:

  • pnpm check passes: 90 test files, 1,532 tests passed (24 skipped).
  • The local TUI starts successfully from this branch.

Supplementary instruction:
PR#35 The Reopen control for the current account is disabled and requires maintenance personnel to perform the operation.

@ZouR-Ma ZouR-Ma closed this Sep 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/cli src/main.ts, src/cli.tsx, src/i18n.ts, src/version.ts, src/utils area/tui src/tui

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TUI transcript 不支持 Markdown 渲染,agent 响应中的代码块、表格、粗体等丢失格式

2 participants